package com.example.ntpsynchronoustime.utils;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

/**
 * @author: njb
 * @date: 2023/7/4 0:01
 * @desc: 从ntp服务器获取网络时间
 */
public class NetworkTimeUtil {
    private final String TAG = "NetworkTime";
    private final int TIMEOUT_MS = 5000;
    private final int NTP_PACKET_SIZE = 48;
    private final int NTP_PORT = 123;
    private String[] str = {"ntp1.aliyun.com", "sg.pool.ntp.org", "tw.pool.ntp.org", "jp.pool.ntp.org", "hk.pool.ntp.org", "time.windows.com", "time.apple.com", "time.asia.apple.com", "dns1.synet.edu.cn", "dns.sjtu.edu.cn", "dns2.synet.edu.cn", "ntp.glnet.edu.cn", "s2g.time.edu.cn", "ntp-sz.chl.la"};
    private int index;

    public long getNetworkTime() {
        long timestamp = 0;
        try {
            DatagramSocket socket = new DatagramSocket();
            socket.setSoTimeout(TIMEOUT_MS);

            InetAddress address = InetAddress.getByName(str[index]);

            byte[] buffer = new byte[NTP_PACKET_SIZE];
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length, address, NTP_PORT);

            // 构造NTP请求包
            buffer[0] = (byte) 0b11100011;
            for (int i = 1; i < NTP_PACKET_SIZE; i++) {
                buffer[i] = 0;
            }
            // 发送NTP请求包
            socket.send(packet);

            // 接收NTP响应包
            packet = new DatagramPacket(buffer, buffer.length);
            socket.receive(packet);

            // 解析NTP响应包，获取网络时间
            timestamp = parseNtpPacket(buffer);

            //获取不到重新请求
            if (timestamp <= 0) {
                socket.close();
                index++;
                if (index < str.length) {
                    getNetworkTime();
                }
            }
            socket.close();
        } catch (SocketTimeoutException e) {
            e.printStackTrace();
            index++;
            if (index < str.length) {
                return getNetworkTime();
            }
        } catch (UnknownHostException e) {//
            index++;
            if (index < str.length) {
                return getNetworkTime();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return timestamp;
    }

    private long parseNtpPacket(byte[] buffer) {
        long timestamp = 0;
        for (int i = 40; i <= 43; i++) {
            timestamp = (timestamp << 8) | (buffer[i] & 0xff);
        }
        timestamp -= 2208988800L;
        return timestamp * 1000;
    }
}
